/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package puertos;

import gnu.io.*;
import interfaz.Principal;
import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.TooManyListenersException;

public class Communicator implements SerialPortEventListener {
    //passed from main GUI

    Principal window = null;
    //for containing the ports that will be found
    private Enumeration ports = null;
    //map the port names to CommPortIdentifiers
    private HashMap portMap = new HashMap();
    //this is the object that contains the opened port
    private CommPortIdentifier selectedPortIdentifier = null;
    private SerialPort serialPort = null;
    //input streams for sending data
    private InputStream input = null;
    //just a boolean flag that i use for enabling
    //and disabling buttons depending on whether the program
    //is connected to a serial port or not
    private boolean bConnected = false;
    //the timeout value for connecting with the port
    final static int TIMEOUT = 2000;
    //some ascii values for for certain things
    final static int SPACE_ASCII = 32;
    final static int DASH_ASCII = 45;
    final static int NEW_LINE_ASCII = 10;
    //a string for recording what goes on in the program
    //this string is written to the GUI
    String logText = "";
    //Control for
    int i = 0;

    public Communicator(Principal window) {
        this.window = window;
    }

    //search for all the serial ports
    //pre: none
    //post: adds all the found ports to a combo box on the GUI
    public void searchForPorts() {
        ports = CommPortIdentifier.getPortIdentifiers();

        while (ports.hasMoreElements()) {
            CommPortIdentifier curPort = (CommPortIdentifier) ports.nextElement();

            //get only serial ports
            if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                window.ensayo.cboxPorts.addItem(curPort.getName());
                window.alambre.cboxPorts.addItem(curPort.getName());
                window.soldadura.cboxPorts.addItem(curPort.getName());
                portMap.put(curPort.getName(), curPort);
            }
        }
    }

    //connect to the selected port in the combo box
    //pre: ports are already found by using the searchForPorts method
    //post: the connected comm port is stored in commPort, otherwise,
    //an exception is generated
    public void connect(String puerto) {
        String selectedPort = puerto;
        selectedPortIdentifier = (CommPortIdentifier) portMap.get(selectedPort);

        CommPort commPort;

        try {
            //the method below returns an object of type CommPort
            commPort = selectedPortIdentifier.open("TigerControlPanel", TIMEOUT);
            //the CommPort object can be casted to a SerialPort object
            serialPort = (SerialPort) commPort;

            //Establecer configuración del puerto
            int baudRate = 9600;

            try {
                serialPort.setSerialPortParams(
                        baudRate,
                        SerialPort.DATABITS_8,
                        SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);
            } catch (UnsupportedCommOperationException ex) {
                System.err.println(ex.getMessage());
            }

            try {
                serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
            } catch (UnsupportedCommOperationException ex) {
                System.err.println(ex.getMessage());
            }

            //for controlling GUI elements
            setConnected(true);

            //logging
            logText = selectedPort + " opened successfully.";
            window.ensayo.txtLog.setForeground(Color.black);
            window.ensayo.txtLog.append(logText + "\n");


        } catch (PortInUseException e) {
            logText = selectedPort + " is in use. (" + e.toString() + ")";
            window.ensayo.txtLog.setForeground(Color.RED);
            window.ensayo.txtLog.append(logText + "\n");
        } catch (Exception e) {
            logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
            window.ensayo.txtLog.append(logText + "\n");
            window.ensayo.txtLog.setForeground(Color.RED);
        }
    }

    //open the input and output streams
    //pre: an open port
    //post: initialized intput and output streams for use to communicate data
    public boolean initIOStream() {
        //return value for whather opening the streams is successful or not
        boolean successful = false;

        try {
            //
            input = serialPort.getInputStream();

            successful = true;
            return successful;
        } catch (IOException e) {
            logText = "I/O Streams failed to open. (" + e.toString() + ")";
            window.ensayo.txtLog.setForeground(Color.red);
            window.ensayo.txtLog.append(logText + "\n");
            return successful;
        }
    }

    //starts the event listener that knows whenever data is available to be read
    //pre: an open serial port
    //post: an event listener for the serial port that knows when data is recieved
    public void initListener() {
        try {
            serialPort.addEventListener(this);
            serialPort.notifyOnDataAvailable(true);
        } catch (TooManyListenersException e) {
            logText = "Too many listeners. (" + e.toString() + ")";
            window.ensayo.txtLog.setForeground(Color.red);
            window.ensayo.txtLog.append(logText + "\n");
        }
    }

    //disconnect the serial port
    //pre: an open serial port
    //post: clsoed serial port
    public void disconnect() {
        //close the serial port
        try {
            serialPort.removeEventListener();
            serialPort.close();
            input.close();
            setConnected(false);

            logText = "Disconnected.";
            window.ensayo.txtLog.setForeground(Color.red);
            window.ensayo.txtLog.append(logText + "\n");
        } catch (Exception e) {
            logText = "Failed to close " + serialPort.getName() + "(" + e.toString() + ")";
            window.ensayo.txtLog.setForeground(Color.red);
            window.ensayo.txtLog.append(logText + "\n");
        }
    }

    final public boolean getConnected() {
        return bConnected;
    }

    public void setConnected(boolean bConnected) {
        this.bConnected = bConnected;
    }

    //what happens when data is received
    //pre: serial event is triggered
    //post: processing on the data it reads
    @Override
    public void serialEvent(SerialPortEvent evt) {
        if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {
                byte singleData = (byte) input.read();
                if (singleData == 61) {
                    i = 0;
                    logText = "";
                } else {
                    logText += new String(new byte[]{singleData});
                    i++;
                    if (i == 7) {
                        window.ensayo.setDatoCeldas(logText);
                        window.alambre.setDatoCeldas(logText);
                        window.soldadura.setDatoCeldas(logText);
                    }
                }
            } catch (Exception e) {
                logText = "Failed to read data. (" + e.toString() + ")";
                window.ensayo.txtLog.setForeground(Color.red);
                window.ensayo.txtLog.append(logText + "\n");
            }
        }
    }
}
